package cn.foolishbird.crow.core.util;

import java.time.LocalDateTime;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 替代common-lang3的RandomUtils，因为使用的是new Random()做静态属性，有线程安全问题
 *
 * @author foolish-bird
 */
public class RandomUtils {

    /**
     * 字符串数组
     */
    private static final String STR = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    public RandomUtils() {
    }

    public static boolean nextBoolean() {
        return ThreadLocalRandom.current().nextBoolean();
    }

    public static byte[] nextBytes(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("Count cannot be negative.");
        }
        byte[] result = new byte[count];
        ThreadLocalRandom.current().nextBytes(result);
        return result;
    }

    public static int nextInt(int startInclusive, int endExclusive) {
        if (startInclusive > endExclusive) {
            throw new IllegalArgumentException("Start value must be smaller or equal to end value.");
        }
        if (startInclusive < 0) {
            throw new IllegalArgumentException("Both range values must be non-negative.");
        }
        return startInclusive == endExclusive ? startInclusive : startInclusive + ThreadLocalRandom.current().nextInt(
                endExclusive - startInclusive);
    }

    public static int nextInt() {
        return nextInt(0, 2147483647);
    }

    public static long nextLong(long startInclusive, long endExclusive) {
        if (startInclusive > endExclusive) {
            throw new IllegalArgumentException("Start value must be smaller or equal to end value.");
        }
        if (startInclusive < 0) {
            throw new IllegalArgumentException("Both range values must be non-negative.");
        }
        return startInclusive == endExclusive ? startInclusive : startInclusive + nextLong(
                endExclusive - startInclusive);
    }

    public static long nextLong() {
        return nextLong(9223372036854775807L);
    }

    private static long nextLong(long n) {
        long bits;
        long val;
        do {
            bits = ThreadLocalRandom.current().nextLong() >>> 1;
            val = bits % n;
        } while (bits - val + (n - 1L) < 0L);

        return val;
    }

    public static double nextDouble(double startInclusive, double endExclusive) {
        if (startInclusive > endExclusive) {
            throw new IllegalArgumentException("Start value must be smaller or equal to end value.");
        }
        if (startInclusive < 0) {
            throw new IllegalArgumentException("Both range values must be non-negative.");
        }
        return startInclusive == endExclusive ? startInclusive
                : startInclusive + (endExclusive - startInclusive) * ThreadLocalRandom.current().nextDouble();
    }

    public static double nextDouble() {
        return nextDouble(0.0D, 1.7976931348623157E308D);
    }

    public static float nextFloat(float startInclusive, float endExclusive) {
        if (startInclusive > endExclusive) {
            throw new IllegalArgumentException("Start value must be smaller or equal to end value.");
        }
        if (startInclusive < 0) {
            throw new IllegalArgumentException("Both range values must be non-negative.");
        }
        return startInclusive == endExclusive ? startInclusive
                : startInclusive + (endExclusive - startInclusive) * ThreadLocalRandom.current().nextFloat();
    }

    public static float nextFloat() {
        return nextFloat(0.0F, 3.4028235E38F);
    }

    /**
     * 时间 + 4位随机数
     *
     * @param randomNum 随机数位数
     * @return 时间 + 4位随机数
     */
    public static String timeRandomStr(int randomNum) {
        return DateTimeUtils.format(LocalDateTime.now(), DateTimeEnum.SIMPLE_DATE_TIME) +
                RandomUtils.createRandomNum(randomNum);
    }

    /**
     * 数字+大写字符串+小写字符串随机
     *
     * @param randomNum 随机树位数
     * @return 随机字符串
     */
    public static String createRandomStr(int randomNum) {
        char[] str = STR.toCharArray();
        StringBuilder random = new StringBuilder();
        for (int i = 0; i < randomNum; i++) {
            int index = ThreadLocalRandom.current().nextInt(str.length);
            random.append(str[index]);
        }
        return random.toString();
    }

    /**
     * 生成有限位数的数字随机字符串
     *
     * @param randomNum 随机位数
     * @return 随机字符串
     */
    public static String createRandomNum(int randomNum) {
        StringBuilder random = new StringBuilder();
        for (int i = 0; i < randomNum; i++) {
            random.append(ThreadLocalRandom.current().nextInt(10));
        }
        return random.toString();
    }


}
